﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Asah.SiteWorx.ProductCatalog;

public partial class SiteWorx_ProductCatalogManager : System.Web.UI.Page
{
    private int _productCatalogId = 0;

    public int MyProductCatalogId
    {
        get
        {
            return _productCatalogId;
        }
        set
        {
            _productCatalogId = value;
            Session["MyCatalog"] = null;
        }
    }

    public Catalog MyCatalog
    {
        get
        {
            if (Session["MyCatalog"] == null)
            {
                MyProduct = null;
                if (MyProductCatalogId > 0)
                    Session["MyCatalog"] = Catalog.GetCatalog(MyProductCatalogId);
                else
                    Session["MyCatalog"] = Catalog.NewCatalog();
            }
            return (Catalog)Session["MyCatalog"];
        }
        set
        {
            Session["MyCatalog"] = value;
        }
    }

    public Product MyProduct
    {
        get
        {
            return (Product)Session["MyProduct"];
        }
        set
        {
            Session["MyProduct"] = value;
        }
    }

    public LinkedList<Guid> MyProductPositionList
    {
        get
        {
            if (Session["MyProductPositionList"] == null)
                Session["MyProductPositionList"] = new LinkedList<Guid>();
            return (LinkedList<Guid>)Session["MyProductPositionList"];
        }
        set
        {
            Session["MyProductPositionList"] = value;
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            // Reset the catalog.
            MyProductCatalogId = 0;
            mvwProductCatalog.SetActiveView(vwCatalogList);
            rgvCatalog.DataBind();
        }
    }

    protected void rgvCatalog_DeleteCommand(object source, Telerik.Web.UI.GridCommandEventArgs e)
    {
        // Delete the selected catalog.
        MyProductCatalogId = int.Parse(((Button)e.Item.FindControl("btnEdit")).CommandArgument);
        MyCatalog.Delete();
        MyCatalog.Save();
        rgvCatalog.DataBind();
    }

    protected void rgvCatalog_ItemCommand(object source, Telerik.Web.UI.GridCommandEventArgs e)
    {
        if (e.CommandName == "Select")
        {
            // Edit the selected catalog.
            MyProductCatalogId = int.Parse(e.CommandArgument.ToString());
            mvwProductCatalog.SetActiveView(vwCatalog);
            mvwProducts.SetActiveView(vwProducts);
            fvProductCatalog.DataBind();
            rgvProducts.DataBind();
        }
    }

    protected void btnAddCatalog_Click(object sender, EventArgs e)
    {
        // Add a new catalog.
        MyProductCatalogId = 0;
        mvwProductCatalog.SetActiveView(vwCatalog);
        mvwProducts.SetActiveView(vwProducts);
        fvProductCatalog.DataBind();
        rgvProducts.DataBind();
    }

    protected void rgvProducts_DeleteCommand(object source, Telerik.Web.UI.GridCommandEventArgs e)
    {
        // Delete the selected product.
        int productId = int.Parse(((Button)e.Item.FindControl("btnEdit")).CommandArgument);
        if (productId > 0)
        {
            MyCatalog.Products.Remove(productId);
        }
        else // no product id so use index instead.
        {
            MyCatalog.Products.RemoveAt(e.Item.ItemIndex);
        }
        rgvProducts.DataBind();
    }

    protected void rgvProducts_ItemCommand(object source, Telerik.Web.UI.GridCommandEventArgs e)
    {
        if (e.CommandName == "Select")
        {
            // Edit the selected product.
            mvwProducts.SetActiveView(vwProduct);
            int productId = int.Parse(e.CommandArgument.ToString());

            if (productId > 0)
            {
                MyProduct = MyCatalog.Products.GetProduct(productId);
            }
            else // no product id so use index instead.
            {
                MyProduct = MyCatalog.Products[e.Item.ItemIndex];
            }

            fvProduct.DataBind();
        }
    }

    protected void btnAddProduct_Click(object sender, EventArgs e)
    {
        // Add a new product.
        MyProduct = MyCatalog.Products.AddNew();
        MyProduct.Position = MyCatalog.Products.Count - 1;
        mvwProducts.SetActiveView(vwProduct);
        fvProduct.DataBind();
    }

    protected void fvProduct_DataBound(object sender, EventArgs e)
    {
        Literal litProductUpdateSection = (Literal)fvProduct.FindControl("litProductUpdateSection");
        ProfileCommon profileCommon;

        if (MyProduct.CreatedDate.Length > 0)
        {
            litProductUpdateSection.Text += "Created at " + MyProduct.CreatedDate;
            if (MyProduct.CreatedBy != null)
            {
                profileCommon = Profile.GetProfile(MyProduct.CreatedBy.Name);
                if (profileCommon.DisplayName.Length > 0)
                    litProductUpdateSection.Text += " by <a href=\"mailto:" + MyProduct.CreatedBy.Email + "\">" + profileCommon.DisplayName + "</a>";
                else
                    litProductUpdateSection.Text += " by <a href=\"mailto:" + MyProduct.CreatedBy.Email + "\">" + MyProduct.CreatedBy.Name + "</a>";
            }
        }

        if (MyProduct.LastUpdatedDate.Length > 0)
        {
            litProductUpdateSection.Text += "<br/>Last updated at " + MyProduct.LastUpdatedDate;
            if (MyProduct.LastUpdatedBy != null)
            {
                profileCommon = Profile.GetProfile(MyProduct.LastUpdatedBy.Name);
                if (profileCommon.DisplayName.Length > 0)
                    litProductUpdateSection.Text += " by <a href=\"mailto:" + MyProduct.LastUpdatedBy.Email + "\">" + profileCommon.DisplayName + "</a>";
                else
                    litProductUpdateSection.Text += " by <a href=\"mailto:" + MyProduct.LastUpdatedBy.Email + "\">" + MyProduct.LastUpdatedBy.Name + "</a>";
            }
        }
    }

    protected void fvProduct_ItemCommand(object sender, FormViewCommandEventArgs e)
    {
        // Cancel the edit on a product and return to the product list.
        switch (e.CommandName)
        {
            case "Cancel":
                // Check for an empty product in the last position in the list and remove it if present
                if (MyCatalog.Products.Count > 0)
                {
                    Asah.SiteWorx.ProductCatalog.Product product = MyCatalog.Products[MyCatalog.Products.Count - 1];
                    if (product.Title.Length == 0)
                        MyCatalog.Products.RemoveAt(MyCatalog.Products.Count - 1);
                }

                mvwProducts.SetActiveView(vwProducts);
                rgvProducts.DataBind();
                break;
        }
    }

    protected void fvProduct_ItemUpdated(object sender, FormViewUpdatedEventArgs e)
    {
        // After product is updated return to the product list.
        mvwProducts.SetActiveView(vwProducts);
        rgvProducts.DataBind();
    }

    #region CSLA Datasource Methods

    protected void cdsProductCatalogList_SelectObject(object sender, Csla.Web.SelectObjectArgs e)
    {
        e.BusinessObject = Asah.SiteWorx.ProductCatalog.CatalogList.GetCatalogList();
    }
    protected void cdsProductCatalog_SelectObject(object sender, Csla.Web.SelectObjectArgs e)
    {
        e.BusinessObject = MyCatalog;
    }

    protected void cdsProductCatalog_UpdateObject(object sender, Csla.Web.UpdateObjectArgs e)
    {
        Csla.Data.DataMapper.Map(e.Values, MyCatalog);
    }

    protected void cdsProducts_SelectObject(object sender, Csla.Web.SelectObjectArgs e)
    {
        var result = from product in MyCatalog.Products
                     orderby product.Position
                     select product;

        MyProductPositionList.Clear();
        foreach (Product product in result)
            MyProductPositionList.AddLast(product.UniqueId);
        e.BusinessObject = result;
    }
    protected void cdsProduct_SelectObject(object sender, Csla.Web.SelectObjectArgs e)
    {
        e.BusinessObject = MyProduct;
    }

    protected void cdsProduct_UpdateObject(object sender, Csla.Web.UpdateObjectArgs e)
    {
        Csla.Data.DataMapper.Map(e.Values, MyProduct);
    }

    #endregion

    protected void btnSave_Click(object sender, EventArgs e)
    {
        // Save the catalog edits and return to the catalog
        fvProductCatalog.UpdateItem(true);
        if (MyCatalog.IsValid)
        {
            MyCatalog = MyCatalog.Save();
            mvwProductCatalog.SetActiveView(vwCatalogList);
            rgvCatalog.DataBind();
        }
        else
        {
            CustomValidator validator;
            foreach (Csla.Validation.BrokenRule rule in MyCatalog.BrokenRulesCollection)
            {
                validator = new CustomValidator();
                validator.ErrorMessage = rule.Description;
                validator.IsValid = false;
                Page.Validators.Add(validator);
            }
        }
    }

    protected void btnCancel_Click(object sender, EventArgs e)
    {
        // Cancel catalog editing and return to the catalog.
        mvwProductCatalog.SetActiveView(vwCatalogList);
        rgvCatalog.DataBind();
    }

    protected void fvProductCatalog_DataBound(object sender, EventArgs e)
    {
        Literal litCatalogUpdateSection = (Literal)fvProductCatalog.FindControl("litCatalogUpdateSection");
        ProfileCommon profileCommon;

        if (MyCatalog.CreatedDate.Length > 0)
        {
            litCatalogUpdateSection.Text += "Created at " + MyCatalog.CreatedDate;
            if (MyCatalog.CreatedBy != null)
            {
                profileCommon = Profile.GetProfile(MyCatalog.CreatedBy.Name);
                if (profileCommon.DisplayName.Length > 0)
                    litCatalogUpdateSection.Text += " by <a href=\"mailto:" + MyCatalog.CreatedBy.Email + "\">" + profileCommon.DisplayName + "</a>";
                else
                    litCatalogUpdateSection.Text += " by <a href=\"mailto:" + MyCatalog.CreatedBy.Email + "\">" + MyCatalog.CreatedBy.Name + "</a>";
            }
        }

        if (MyCatalog.LastUpdatedDate.Length > 0)
        {
            litCatalogUpdateSection.Text += "<br/>Last updated at " + MyCatalog.LastUpdatedDate;
            if (MyCatalog.LastUpdatedBy != null)
            {
                profileCommon = Profile.GetProfile(MyCatalog.LastUpdatedBy.Name);
                if (profileCommon.DisplayName.Length > 0)
                    litCatalogUpdateSection.Text += " by <a href=\"mailto:" + MyCatalog.LastUpdatedBy.Email + "\">" + profileCommon.DisplayName + "</a>";
                else
                    litCatalogUpdateSection.Text += " by <a href=\"mailto:" + MyCatalog.LastUpdatedBy.Email + "\">" + MyCatalog.LastUpdatedBy.Name + "</a>";
            }
        }
    }

    protected void rgvProducts_RowDrop(object sender, Telerik.Web.UI.GridDragDropEventArgs e)
    {
        try  // try to move the row however if it fails we just ignore it.
        {
            Guid draggedProductId = (Guid)e.DraggedItems[0].GetDataKeyValue("UniqueId");
            Guid destProductId = (Guid)e.DestDataItem.GetDataKeyValue("UniqueId");

            // first we remove the product id from the list.
            MyProductPositionList.Remove(draggedProductId);

            // next we find the destination product id and either add before or after the dragged product id.
            LinkedListNode<Guid> currentNode = MyProductPositionList.First;
            bool keepLooping = true;
            while (currentNode != null && keepLooping)
            {
                if (currentNode.Value == destProductId) // found the destination product id.
                {
                    switch (e.DropPosition)
                    {
                        case Telerik.Web.UI.GridItemDropPosition.Above:
                            MyProductPositionList.AddBefore(currentNode, draggedProductId);
                            keepLooping = false;
                            break;
                        case Telerik.Web.UI.GridItemDropPosition.Below:
                            MyProductPositionList.AddAfter(currentNode, draggedProductId);
                            keepLooping = false;
                            break;
                    }
                }
                currentNode = currentNode.Next;
            }

            // finally we need to update the products collection with the new positions.
            int index = 0;
            Product product = null;

            foreach (Guid productUniqueId in MyProductPositionList)
            {
                product = MyCatalog.Products.GetProduct(productUniqueId);
                if (product.Position != index)
                    product.Position = index;
                index++;
            }

            rgvProducts.Rebind();
        }
        catch
        {
        }
    }
}